﻿/*
	This file is part of Limpet.

    Limpet is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Limpet is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with Limpet.  If not, see http://www.gnu.org/licenses/.
	
	Copyright 2010 Dan Popick
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.Caching;
using System.Web.SessionState;
using System.Web.UI;
using System.Xml;
using System.Xml.Serialization;

namespace Open.Web.Diagnostics.Limpet.Modules
{
    /// <summary>
    /// The session module displays data on the current ASP.NET session's contents
    /// </summary>
    public class SessionModule: ISelfRenderingLimpetModule
    {
        /// <summary>
        /// Controls whether the objects are serialized into XML or just converted to strings
        /// using ToString()
        /// </summary>
        public bool ConvertToXml { get; set; }

        public SessionModule(string name, XmlNode configurationNode)
        {
            Name = name;
            ConvertToXml = true;
        }

        #region ISelfRenderingLimpetModule Members

        /// <summary>
        /// Renders the details for this module 
        /// </summary>
        /// <param name="stream">
        /// A <see cref="Stream"/> on which to write the contents of the details
        /// </param>
        public void RenderDetails(Stream stream)
        {
            HttpSessionState session = HttpContext.Current.Session;

            TextWriter tw = new StreamWriter(stream);
            HtmlTextWriter writer = new HtmlTextWriter(tw);

            writer.BeginRender();
            writer.RenderBeginTag(HtmlTextWriterTag.H2);
            writer.WriteEncodedText("Session");
            writer.RenderEndTag();

            if (session == null)
            {
                writer.RenderBeginTag(HtmlTextWriterTag.P);
                writer.WriteEncodedText("No session found.");
                writer.RenderEndTag();
                writer.Flush();
                return;
            }

            writer.RenderBeginTag(HtmlTextWriterTag.Table);
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
                writer.RenderBeginTag(HtmlTextWriterTag.Th);
                writer.WriteEncodedText("Key");
                writer.RenderEndTag();
                writer.RenderBeginTag(HtmlTextWriterTag.Th);
                writer.WriteEncodedText("Value");
                writer.RenderEndTag();
            writer.RenderEndTag();

            List<string> keys = new List<string>();
            foreach (string key in session.Keys) keys.Add(key);
            keys.Sort();
            foreach (string key in keys)
            {
                if (key.StartsWith("_limpet"))
                    continue;

                writer.RenderBeginTag(HtmlTextWriterTag.Tr);
                writer.RenderBeginTag(HtmlTextWriterTag.Td);
                writer.WriteEncodedText(key);
                writer.RenderEndTag();
                writer.RenderBeginTag(HtmlTextWriterTag.Td);
                writer.Write("<pre>");
                writer.WriteEncodedText(Serialize(session[key]));
                writer.Write("</pre>");
                writer.RenderEndTag();
                writer.RenderEndTag();
            }
            writer.RenderEndTag();

            writer.Flush();
        }

        #endregion

        string Serialize(object obj)
        {
            Type type = obj.GetType();

            try
            {
                XmlSerializer xser = new XmlSerializer(type);
                StringWriter sw = new StringWriter();
                XmlWriter xw = XmlWriter.Create(sw, new XmlWriterSettings()
                {
                    Indent = true,
                    IndentChars = "   ",
                    OmitXmlDeclaration = true
                });

                XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
                ns.Add(String.Empty, String.Empty);
                xser.Serialize(xw, obj, ns);
                xw.Flush();

                return sw.ToString();
            }
            catch { }

            return obj.ToString();
        }

        #region ILimpetModule Members

        /// <summary>
        /// The name, as defined in the config file
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Gets a single-line HTML message to display in the Limpet popup.
        /// </summary>
        /// <param name="context">The current HTTP context</param>
        /// <returns>A string of HTML to display in the popup.</returns>
        public SummaryMessage GetMessage(System.Web.HttpContext context)
        {
            HttpSessionState session = HttpContext.Current.Session;
            string summary;
            if (session.Count > 1)
                summary = session.Count.ToString() + " entries";
            else if (session.Count > 0)
                summary = session.Count.ToString() + " entry";
            else
                summary = "No entries";

            return new SummaryMessage()
            {
                Category = "Session",
                Severity = LimpetSeverity.Debug,
                Text = (session == null) 
                    ? "No session" 
                    : summary,
                Url = LimpetManager.GetSelfRenderingUrl(Name)
            };
        }

        #endregion
    }
}
